﻿using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Vin.Extension.Framework.Monitor.Constants;
using Vin.Extension.Framework.Monitor.Entities;
using Vin.Extension.Framework.Monitor.Options;
using Vin.Extension.Framework.Monitor.ServiceInterface;
using Vin.Extension.Redis.Cache;
using Vin.Tool.AspNetCore.Singleton;
using Vin.Tool.Core.BasicTypeCategory;

namespace Vin.Extension.Framework.Monitor.BackgroundServices;

public class RequestLogBackgroundService : BackgroundService
{
    private IOptionsMonitor<MonitorOption> _optionsMonitor;
    private MonitorOption Option => _optionsMonitor.CurrentValue;

    public RequestLogBackgroundService(IOptionsMonitor<MonitorOption> optionsMonitor)
    {
        _optionsMonitor = optionsMonitor;
    }

    private Task ProcessAsync(int index, CancellationToken stoppingToken)
    {
        return VinApp.CreateScopeAsync(async provider =>
        {
            var redisCache = RedisCacheManager.GetRedisCache();
            var requestLogService = provider.GetRequiredService<ISysRequestLogService>();
            while (!stoppingToken.IsCancellationRequested)
            {
                try
                {
                    long cursor = 0;

                    do
                    {
                        var result = await redisCache.ScanAsync(cursor,
                            MonitorConstants.RequestLogKey.Format(index, "*"),
                            Option.BatchSize);
                        cursor = result.cursor;

                        var list = result.items.ToList();

                        #region 处理数据

                        foreach (var key in list)
                        {
                            var log = await redisCache.GetCacheAsync<SysRequestLog>(key);
                            if (log != null)
                            {
                                if (await requestLogService.SaveAsync(log))
                                {
                                    await redisCache.RemoveCacheAsync(key);
                                }
                            }
                        }

                        #endregion
                    } while (cursor > 0);

                    // 如果没有数据则等待5秒
                    await Task.Delay(Option.WaitSeconds * 1000);
                }
                catch (System.Exception e)
                {
                    provider.GetRequiredService<ILogger<RequestLogBackgroundService>>()
                        .LogError(e, "RequestLogBackgroundService Error");
                    await Task.Delay(5000);
                }
            }
        });
    }


    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {
        var tasks = new List<Task>();
        for (var i = 0; i < Option.ThreadSize; i++)
        {
            tasks.Add(ProcessAsync(i, stoppingToken));
        }

        await Task.WhenAll(tasks);
    }
}